----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    14:31:46 04/11/2008 
-- Design Name: 
-- Module Name:    MemoryManager - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity MemoryManager is
    Port ( write_address : in  STD_LOGIC_VECTOR (17 downto 0);
           write_data : in STD_LOGIC_VECTOR (15 downto 0);
           req_write : in  STD_LOGIC;
           ack_write : out STD_LOGIC;
           display_address : in STD_LOGIC_VECTOR (17 downto 0);
           display_data : out STD_LOGIC_VECTOR (31 downto 0);
           req_read : in STD_LOGIC;
           ack_read : out STD_LOGIC;          
           ram_address : out  STD_LOGIC_VECTOR (17 downto 0);
           ram_data : inout  STD_LOGIC_VECTOR (15 downto 0);
			  req_get : in STD_LOGIC;
			  ack_get : out STD_LOGIC;
			  get_address : in STD_LOGIC_VECTOR(17 downto 0);
			  get_data : out STD_LOGIC_VECTOR(15 downto 0);
           we_n : out  STD_LOGIC;
           oe_n : out STD_LOGIC;
           clk : in  STD_LOGIC);
end MemoryManager;

   
architecture Behavioral of MemoryManager is 

   signal write_flag : std_logic;
	signal memory_address : std_logic_vector(17 downto 0);
   type t_state is (idle, read0, read1, read2, write0, write1, get0, get1);
   signal state, next_state : t_state := idle;

begin
                                       
   update : process(clk)
   begin
      if rising_edge(clk) then
         state <= next_state;
         if state = read0 then display_data(31 downto 16) <= ram_data; end if;
         if state = read2 then display_data(15 downto  0) <= ram_data; end if;
			ram_address <= memory_address;
			if state = get1 then
				ack_get <= '1';
				get_data <= ram_data;
			end if;
			if req_get = '0' then ack_get <= '0'; end if;
      end if;
   end process;
     
   sm : process(clk)
   begin
   
      we_n <= '1';
      oe_n <= '1';
      ack_read <= '0';
      ack_write <= '0';
      write_flag <= '0';
      next_state <= idle;
					
      case state is
         when idle =>
            memory_address <= display_address(17 downto 1) & '0';
            if req_read = '1' then
               oe_n <= '0';
               next_state <= read0;
            elsif req_write = '1' then
               write_flag <= '1';
               memory_address <= write_address(17 downto 0);
               next_state <= write0;
				elsif req_get = '1' then
					memory_address <= get_address(17 downto 0);
					oe_n <= '0';
					next_state <= get0;
            end if;
               
         when read0 =>
            oe_n <= '0';
            memory_address <= display_address(17 downto 1) & '0';
            next_state <= read1;
         when read1 =>
            oe_n <= '0';
            memory_address <= display_address(17 downto 1) & '1';
            --ack_read <= '1';
            next_state <= read2;
			when read2 =>
            oe_n <= '0';
            memory_address <= display_address(17 downto 1) & '1';
            ack_read <= '1';
			
         when write0 =>
            write_flag <= '1';
            memory_address <= write_address(17 downto 0);
            we_n <= '0';
            next_state <= write1;
         when write1 =>
            write_flag <= '1';
            memory_address <= write_address(17 downto 0);
            ack_write <= '1';
            next_state <= idle;     

			when get0 =>
				oe_n <= '0';
				memory_address <= get_address(17 downto 0);
				next_state <= get1;
			when get1 =>
				oe_n <= '0';
				memory_address <= get_address(17 downto 0);
				next_state <= idle;
				
      end case;
      
   end process;

   ram_data <= write_data when write_flag = '1' else (others=>'Z');

end Behavioral;

